package com.code.ape.codeape.inhos.mq.callback;

import com.alibaba.fastjson.JSON;
import com.code.ape.codeape.common.core.util.SpringContextHolder;
import com.code.ape.codeape.inhos.api.entity.MsgRecord;
import com.code.ape.codeape.inhos.api.entity.constant.MsgStatusEnum;
import com.code.ape.codeape.inhos.mapper.MsgRecordMapper;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.SendStatus;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author 公众号：码猿技术专栏
 * @url: www.java-family.cn
 * @description MQ的异步消息的回调
 */
@AllArgsConstructor
@NoArgsConstructor
@Data
@Slf4j
public class PatMsgSendCallback implements SendCallback {

	@Schema(description = "消息ID")
	private Long id;

	/**
	 * 消息发送成功的回调
	 */
	@Transactional
	@Override
	public void onSuccess(SendResult sendResult) {
		if (log.isDebugEnabled())
			log.debug("消息回调成功，回调信息：{}", JSON.toJSONString(sendResult));
		MsgRecordMapper msgRecordMapper = SpringContextHolder.getBean(MsgRecordMapper.class);
		MsgRecord msgRecord = MsgRecord.builder()
				.id(id)
				.failNum(sendResult.getSendStatus().equals(SendStatus.SEND_OK)?0:1)
				.status(sendResult.getSendStatus().equals(SendStatus.SEND_OK) ? MsgStatusEnum.MSG_SUCCESS.getValue() : MsgStatusEnum.MSG_FAIL.getValue())
				.msgId(sendResult.getMsgId()).build();
		//step2 更新，这里需要判断消息的状态，只有已发送||发送失败的状态的才能更新，避免把发送成功的状态再次更新
		msgRecordMapper.updateStatus(msgRecord);
	}

	/**
	 * 消息发送失败的回调
	 * @param throwable
	 */
	@Override
	public void onException(Throwable throwable) {
		if (log.isDebugEnabled())
			log.debug("消息发送异常，回调信息：{}", throwable.getLocalizedMessage());
		//step1 重置消息表的状态
		MsgRecordMapper msgRecordMapper = SpringContextHolder.getBean(MsgRecordMapper.class);
		MsgRecord msgRecord = MsgRecord.builder()
				.id(id)
				.failNum(1)
				.status(MsgStatusEnum.MSG_FAIL.getValue())
				.exceptionMsg(throwable.getLocalizedMessage())
				.build();
		//step2 更新，这里需要判断消息的状态，只有已发送||发送失败的状态的才能更新，避免把发送成功的状态再次更新
		msgRecordMapper.updateStatus(msgRecord);
	}
}
